"""
This is a wrapper that implements various HTTP servers that interface
with WSGI

This is an adaptation of the runfgi command and uses servers that
match flup's WSGIServer interface.

Run with the extra option "help" for a list of additional options you can
pass to this server.
"""
HTTP_HELP = r"""
  Run this project as a fastcgi (or some other protocol supported
  by flup) application. To do this, the flup package from
  http://www.saddi.com/software/flup/ is required.

   runhttp [options] [server settings]

Examples:
  Run a "standard" http process at localhost:80
    $ manage.py runhttp

  Run a twisted web2 http server on a TCP host/port
    $ manage.py runhttp protocol=twisted-web2 host=127.0.0.1 port=8025

  Run a cherrypy http server as a daemon and write the spawned PID in a file
    $ manage.py runfcgi method=prefork \ 
        daemonize=true pidfile=/var/run/django-http.pid

"""



import sys, os
from django.core.management.base import CommandError, BaseCommand, LabelCommand
from optparse import make_option


__all__ = ("runhttp",)

class Command(BaseCommand):
    option_list = LabelCommand.option_list + (
        make_option('-s', '--handler', metavar="MODULE", 
            help=("The handler module that allows django port authority to "
                "interface with the server. Read the documentation for more "
                "information. Default='port_authority.handlers.cherrywsgi'"),
            default='port_authority.handlers.cherrywsgi'),
        make_option('-a','--host', metavar="HOSTNAME", default='localhost',
            help="hostname to listen on. You can specify the port here as \
                well, e.g. localhost:80"),
        make_option('-p', '--port', metavar='PORT', default=8000, 
            help="port to listen on"),
        make_option('-t', '--terminal', action='store_true', default=False,
            help='Don\'t daemonize the the process. Stay in terminal'),
        make_option('-d', '--workdir', default='/', metavar="PATH", 
            help=("change to this directory when daemonizing"
            "(if you don't understand why this is important, don't specify)")),
        make_option('-f', '--pidfile', metavar='FILE', default='/tmp/port-authority.pkl', 
            help="File to store the process id in"),
        make_option('-i', '--stdin', metavar='FILE', default='/dev/null',
            help="File to read for stdin"),
        make_option('-o', '--stdout', metavar='FILE', default='/dev/null',
            help='write stdout to this file'),
        make_option('-e', '--stderr', metavar='FILE', default='/dev/null',
            help='write stdin to this file'),
        make_option('-u', '--umask', metavar='UMASK', default=022,
            help='umask that the daemon will run with'),
        make_option('--user', metavar='UID', 
            help="A user id for the daemon to run as. This requires root access"),
        make_option('-g', '--group', metavar='GID',
            help="A group ID to run in, this might require root permissions"),
        make_option('--setting', metavar='MODULE', default=None,
            help="The settings module. Defaults to the manage.py module")
    )
    help = HTTP_HELP

    requires_model_validation = True
    can_import_settings = True

    def handle(self, action, **options):
        setting = options.pop('setting')
        if setting:
            from django.core.management import setup_environ
            try:
                setting_module = __import__(setting, {}, {}, [''])
            except ImportError:
                raise CommandError("Can't import the settings file")
            setup_environ(setting_module)
        handler_module = options.pop('handler')
        try:
            handler = __import__(handler_module,{}, {}, ['']) 
        except ImportError, e:
            import sys, traceback
            _,_,tb = sys.exc_info()
            tb_info = traceback.extract_tb(tb)
            if tb_info[-1][0] == __file__:
                # If the error occured in this file it's our fault
                raise CommandError("Can't import the %s server " %\
                    server_module)
            else:
                # Otherwise it's someone else's fault, reraise
                raise
        WSGIServer = handler.WSGIServer
        # Prep up and go
        daemonize = not options.pop('terminal')
        server = WSGIServer(**options)
        
        if action == 'start':
            server.start(daemonize)
        elif action == 'restart':
            server.restart()
        elif action == 'stop':
            server.stop()
        else:
            raise CommandError('Action is not recognized')

